# -*- coding: utf-8 -*-
"""
Created on Tue Oct  4 20:19:40 2016

@author: zxj
"""

'''
Facotory实现bulidProtocol的过程：
通过设置在protocol变量上的Protocol类来生成创建一个Protocol实例，
该实例设置其factory属性指向产生该实例的引用，这样同一个factory产生的
Protocol之间能够共享数据。一个Factory可以创建多个Protocol
1.bulidProtocol由Twisted调用
2.Protocol被创建后，接着Twsited通过makeConnection与一个Transport联系起来，Twisted提供了默认实现
默认情况是makeConnection将一个引用赋给Protocol的transport属性，同时设置connected属性为True
3.初始化完成，Protocol将底层的数据转换成高层协议规定的格式化消息，处理接受到的数据的主要方法是dataRecived

'''

class Factory:
    """
    This is a factory which produces protocols.
    创建协议的工厂
    

    By default, buildProtocol will create a protocol of the class given in
    self.protocol.
    默认，bulidProtocol将会创建一个self.protocol给定的协议类
    """

    # put a subclass of Protocol here:
    protocol = None

    numPorts = 0
    noisy = True

    @classmethod
    def forProtocol(cls, protocol, *args, **kwargs):
        """
        Create a factory for the given protocol.
        创建一个给定协议的工厂，

        It sets the C{protocol} attribute and returns the constructed factory
        instance.
        设置protocol属性，返回构造好的工厂实例

        @param protocol: A L{Protocol} subclass

        @param args: Positional arguments for the factory.

        @param kwargs: Keyword arguments for the factory.

        @return: A L{Factory} instance wired up to C{protocol}.
        """
        factory = cls(*args, **kwargs)
        factory.protocol = protocol
        return factory


    def logPrefix(self):
        """
        Describe this factory for log messages.
        """
        return self.__class__.__name__


    def doStart(self):
        """Make sure startFactory is called.
        保证startFactory被调用
        Users should not call this function themselves!
        用户不应该自己调用这个函数
        """
        if not self.numPorts:
            if self.noisy:
                _loggerFor(self).info("Starting factory {factory!r}",
                                      factory=self)
            self.startFactory()
        self.numPorts = self.numPorts + 1

    def doStop(self):
        """Make sure stopFactory is called.
        保证stopFactory被调用，用户不应该自己调用这个函数
        Users should not call this function themselves!
        """
        if self.numPorts == 0:
            # this shouldn't happen, but does sometimes and this is better
            # than blowing up in assert as we did previously.
            return
        self.numPorts = self.numPorts - 1
        if not self.numPorts:
            if self.noisy:
                _loggerFor(self).info("Stopping factory {factory!r}",
                                      factory=self)
            self.stopFactory()

    def startFactory(self):
        """This will be called before I begin listening on a Port or Connector.

        It will only be called once, even if the factory is connected
        to multiple ports.

        This can be used to perform 'unserialization' tasks that
        are best put off until things are actually running, such
        as connecting to a database, opening files, etcetera.
        在我开始监听一个Port或者Connector的时候这个将被被调用
        它只会被调用一次，即使这个工厂被连接到多个端口上。这用于执行'unserialization' 任务，
        这些任务最好被推迟，直到事情实际运行的时候，例如打开一个文件、数据库连接
        
        
        """

    def stopFactory(self):
        """This will be called before I stop listening on all Ports/Connectors.
        在我停止监听所有Ports/Connectors的时候被调用
        This can be overridden to perform 'shutdown' tasks such as disconnecting
        database connections, closing files, etc.
        此被重写用于执行一些关闭操作，例如断开数据库的连接，关闭文件等
        It will be called, for example, before an application shuts down,
        if it was connected to a port. User code should not call this function
        directly.
        """
    def buildProtocol(self, addr):
        """
        Create an instance of a subclass of Protocol.
        创建一个Protocol子类的实例
        The returned instance will handle input on an incoming server
        connection, and an attribute "factory" pointing to the creating
        factory.
        Protocol的factory属性将会指向创建的factory
        返回的实例将会处理一个incoming服务器连接上的输入
        Alternatively, L{None} may be returned to immediately close the
        new connection.
        None也许被返回，将会立即关闭这个连接

        Override this method to alter how Protocol instances get created.
        重写这个方法将能够改变如何Protocol实例被创建

        @param addr: an object implementing L{twisted.internet.interfaces.IAddress}
        addr:实现了twisted.internet.interfaces.IAddress的对象
        """
        p = self.protocol()
        p.factory = self
        return p
        
        
class IProtocolFactory(Interface):
    """
    Interface for protocol factories.
    """

    def buildProtocol(addr):
        """
        Called when a connection has been established to addr.
        当连接被建立的时候被调用

        If None is returned, the connection is assumed to have been refused,
        and the Port will close the connection.

        @type addr: (host, port)
        @param addr: The address of the newly-established connection

        @return: None if the connection was refused, otherwise an object
                 providing L{IProtocol}.
        """

    def doStart():
        """
        Called every time this is connected to a Port or Connector.
        """

    def doStop():
        """
        Called every time this is unconnected from a Port or Connector.
        """


